package com.huntero.picscale;

import android.animation.AnimatorSet;
import android.animation.ObjectAnimator;
import android.animation.PropertyValuesHolder;
import android.animation.ValueAnimator;
import android.content.ContentResolver;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.view.PagerAdapter;
import android.support.v4.view.ViewPager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewGroup;
import android.view.ViewTreeObserver;
import android.widget.ImageView;

import java.io.FileNotFoundException;
import java.util.Arrays;

public class MainActivity extends AppCompatActivity {

    public static final String TAG = "OnTouch";
//    ImageView imageView;
    PreviewViewPager viewPager;
    MatrixScaleTouchListener mTouchListener = null;
    class ImagePreviewAdapter extends PagerAdapter{

        Bitmap bitmap;

        public ImagePreviewAdapter(Bitmap bitmap) {
            this.bitmap = bitmap;
        }

        @Override
        public int getCount() {
            return 5;
        }

        @Override
        public boolean isViewFromObject(@NonNull View view, @NonNull Object o) {
            return view == o;
        }

        @Override
        public void destroyItem(@NonNull ViewGroup container, int position, @NonNull Object object) {
            container.removeView((View) object);
        }

        @NonNull
        @Override
        public Object instantiateItem(@NonNull ViewGroup container, int position) {
            View view = LayoutInflater.from(container.getContext()).inflate(R.layout.item_page_adapter, container, false);
            ScaleImageView imageView = view.findViewById(R.id.image);
            imageView.setImageBitmap(bitmap);
            imageView.setmOnChildMovingListener(viewPager);
            container.addView(view, 0);
            return view;
        }
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        viewPager = findViewById(R.id.viewPager);
//        imageView = findViewById(R.id.image);
        ///sdcard/DCIM/P90107-173329.jpg
        ///storage/self/primary/DCIM/P90107-173329.jpg
//        File f = new File(Environment.getExternalStorageDirectory().getAbsolutePath() + "/sdcard/DCIM/P90107-173329.jpg");
//        File f = new File("/storage/self/primary/DCIM/P90107-173329.jpg");
//        boolean exists = f.exists();
//        Log.i(TAG, "MatrixScaleTouchListener: " + f.getAbsolutePath() + ", " + exists);
//        Uri uri = Uri.fromFile(f);
//        Log.i(TAG, "onCreate: " + uri.toString());
//        imageView.setImageURI(uri);
//
//        imageView.setOnTouchListener(new MatrixScaleTouchListener(imageView));

        Intent intent = new Intent();
        /* 开启Pictures画面Type设定为image */
        intent.setType("image/*");
        /* 使用Intent.ACTION_GET_CONTENT这个Action */
        intent.setAction(Intent.ACTION_GET_CONTENT);
        /* 取得相片后返回本画面 */
        startActivityForResult(intent, 1);

    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == RESULT_OK) {
            Uri uri = data.getData();
            String img_url = uri.getPath();//这是本机的图片路径
            Log.i(TAG, "onActivityResult: " + img_url);
            ContentResolver cr = this.getContentResolver();
            try {
                Bitmap bitmap = BitmapFactory.decodeStream(cr.openInputStream(uri));
                /* 将Bitmap设定到ImageView */
//                imageView.setImageBitmap(bitmap);
                ImagePreviewAdapter adapter = new ImagePreviewAdapter(bitmap);
                viewPager.setAdapter(adapter);
            } catch (FileNotFoundException e) {
                Log.e("Exception", e.getMessage(),e);
            }
        }
    }

    class MatrixScaleTouchListener implements View.OnTouchListener{

        private float mStartX,mStartY;
        private float mCurrentX, mCurrentY;
        private PointF mScaleCenter = new PointF();

        public static final int MODE_NONE = 0;
        public static final int MODE_DRAG = 1;
        public static final int MODE_SCALE = 2;
        private int mMode = MODE_NONE;

        private final ImageView mImageView;
        private final float[] mOriginalValues = new float[9];
        Matrix mOriginalMatrix;
        Matrix mCurrentMatrix = new Matrix();
        private final float mImageHeight;
        private final float mImageWidth;
        private float mStartDist;
        private float mWidgetWidth;
        private float mWidgetHeight;

        public MatrixScaleTouchListener(ImageView imageView){
            mImageView = imageView;
            //
            mWidgetWidth = mImageView.getWidth();
            mWidgetHeight = mImageView.getHeight();
            mOriginalMatrix = mImageView.getImageMatrix();
            mOriginalMatrix.getValues(mOriginalValues);

            Log.i(TAG, "MatrixScaleTouchListener: mOriginalValues=" + Arrays.toString(mOriginalValues));
            mImageWidth = (mWidgetWidth - mOriginalValues[Matrix.MTRANS_X] * 2) / mOriginalValues[Matrix.MSCALE_X];
            mImageHeight = (mWidgetHeight - mOriginalValues[Matrix.MTRANS_Y] * 2) / mOriginalValues[Matrix.MSCALE_Y];
            Log.i(TAG, "MatrixScaleTouchListener: w=" + mImageWidth + ", h=" + mImageHeight);
        }

        private boolean isScaled(){
            float[] v = new float[9];
            mImageView.getImageMatrix().getValues(v);
            float scale = v[Matrix.MSCALE_X];
            return scale != mOriginalValues[Matrix.MSCALE_X];
        }
        private float calcuDistance(MotionEvent event){
            float x2 = event.getX(1);
            float y2 = event.getY(1);
            float x1 = event.getX(0);
            float y1 = event.getY(0);
            float dx = x2 - x1;
            float dy = y2 - y1;
            mScaleCenter.set((x1 + x2) / 2,(y1 + y2) / 2);
            return (float) Math.sqrt(dx * dx + dy * dy);
        }
        @Override
        public boolean onTouch(View v, MotionEvent event) {
            final int action = event.getAction();
            switch (action & MotionEvent.ACTION_MASK) {
                case MotionEvent.ACTION_DOWN:
                    //单指按下
                    mStartX = event.getX();
                    mStartY = event.getY();
                    mMode = MODE_DRAG;
                    Log.i(TAG, "onTouch: start=" + mStartX + ", " + mStartY);
                    break;
                case MotionEvent.ACTION_POINTER_DOWN:
                    //多指按下
                    mMode = MODE_SCALE;
                    mStartDist = calcuDistance(event);
                    break;
                case MotionEvent.ACTION_MOVE:
                    //移动
                    mCurrentX = event.getX();
                    mCurrentY = event.getY();
                    Log.i(TAG, "onTouch: curr=" + mCurrentX + ", " + mCurrentY);

                    if (mMode == MODE_DRAG) {//移动
                        doDrag();
                    } else if (mMode == MODE_SCALE) {//缩放
                        doScale(event);
                    }
                    mStartX = mCurrentX;
                    mStartY = mCurrentY;
                    break;
                case MotionEvent.ACTION_POINTER_UP:
                    //多指抬起：修改平移和缩放的标识的时机
                    Log.i(TAG, "onTouch: ACTION_POINTER_UP");
                    mMode = MODE_DRAG;
                    //
                    resetScaleOrBounds();
                    break;
                case MotionEvent.ACTION_UP:
                    //单指抬起
                    Log.i(TAG, "onTouch: ACTION_UP");
                    calcuBounds();
                    mMode = MODE_NONE;
                    break;
            }
            Log.i(TAG, "onTouch: action=" + (action & MotionEvent.ACTION_MASK) + ", mode=" + mMode);
            return true;
        }
        //缩放
        private void doScale(MotionEvent event) {
            mCurrentMatrix.set(mImageView.getImageMatrix());
            float endDist = calcuDistance(event);
            float scale = endDist / mStartDist;

            Log.i(TAG, "onTouch: scale=" + scale);
            mCurrentMatrix.postScale(scale, scale, mScaleCenter.x, mScaleCenter.y);
            mImageView.setImageMatrix(mCurrentMatrix);
            mStartDist = endDist;
        }
        //滑动
        private void doDrag() {
            if (isScaled()) {
                //缩放，可以移动
                mCurrentMatrix.set(mImageView.getImageMatrix());
                float[] curValues = new float[9];
                mCurrentMatrix.getValues(curValues);
                float dx = mCurrentX - mStartX;
                if (mWidgetWidth >= mImageWidth * curValues[Matrix.MSCALE_X]) {
                    dx = 0f;
                }
                float dy = mCurrentY - mStartY;
                if (mWidgetHeight >= mImageHeight * curValues[Matrix.MSCALE_Y]) {
                    dy = 0f;
                }

                if (Math.sqrt(dx * dx + dy * dy) >= 4f){
                    mCurrentMatrix.postTranslate(dx, dy);
                    mImageView.setImageMatrix(mCurrentMatrix);
                }
            }
        }

        private void resetScaleOrBounds() {
            calcuScales();
            //是否需要移动
            calcuBounds();
        }

        private void calcuScales() {
            float[] currValues = new float[9];
            mCurrentMatrix.set(mImageView.getImageMatrix());
            mCurrentMatrix.getValues(currValues);
            Log.i(TAG, "calcuScales: orig=" + Arrays.toString(mOriginalValues));
            Log.i(TAG, "calcuScales: curr=" + Arrays.toString(currValues));

            //判断是否超过最大缩放值
            float scale = 1f;
            float p = currValues[Matrix.MSCALE_X] / mOriginalValues[Matrix.MSCALE_X];
            if (p  >= 8f) {
                scale = 8f / p;
            }

            //判断是否低于原始显示的缩放值
            if (p <= 1f) {
                scale = 1 / p;
            }

            Log.i(TAG, "calcuScales: ratio=" + p + ", scale=" + scale);
            if(scale != 1f) {
                mCurrentMatrix.postScale(scale, scale, mScaleCenter.x, mScaleCenter.y);
                mImageView.setImageMatrix(mCurrentMatrix);
            }
        }

        private void calcuBounds() {
            float[] currValues = new float[9];
            mCurrentMatrix.set(mImageView.getImageMatrix());
            mCurrentMatrix.getValues(currValues);
            Log.i(TAG, "calcuBounds: curr=" + Arrays.toString(currValues));

            float dx = calcuDxBound(currValues);
            float dy = calcuDyBound(currValues);

            if(dx != 0 || dy != 0) {
                mCurrentMatrix.postTranslate(dx, dy);
                mImageView.setImageMatrix(mCurrentMatrix);
            }
        }

        private float calcuDyBound(float[] currValues) {
            float dy = 0f;
            float displayHeight = mImageHeight * currValues[Matrix.MSCALE_Y];
            if(mWidgetHeight >= displayHeight){
                //居中y轴，x轴不动
                dy = (mWidgetHeight - displayHeight) / 2 - currValues[Matrix.MTRANS_Y];
            }else{
                //防止超区域
                float max = 0,min = mWidgetHeight - displayHeight;
                float y = currValues[Matrix.MTRANS_Y];

                if(y < min){
                    dy = min - y;
                }
                if(y > max){
                    dy = max - y;
                }
            }
            Log.i(TAG, "calcuDyBound: widgetH=" + mWidgetHeight + ", display=" + displayHeight + ", y=" + currValues[Matrix.MTRANS_Y] + ", dy=" + dy);
            return dy;
        }

        private float calcuDxBound(float[] currValues) {
            float dx = 0f;
            float displayWidth = mImageWidth * currValues[Matrix.MSCALE_X];
            if(mWidgetWidth >= displayWidth){
                //居中x轴，y轴不动
                dx = (mWidgetWidth - displayWidth) / 2 - currValues[Matrix.MTRANS_X];
            }else{
                //防止超区域
                float max = 0,min = mWidgetWidth - displayWidth;
                float x = currValues[Matrix.MTRANS_X];
                if(x < min){
                    dx = min - x;
                }
                if(x > max){
                    dx = max - x;
                }
            }
            Log.i(TAG, "calcuDxBound: widgetW=" + mWidgetWidth + ", display=" + displayWidth + ", x=" +  currValues[Matrix.MTRANS_X] + ", dx=" + dx);
            return dx;
        }

    }
}
